#include "serialmanager.h"

#include <QSerialPortInfo>

#include <QDebug>

SerialPortManager::SerialPortManager(bool isSimulate, QObject *parent) : QObject(parent), m_isSimulate(isSimulate)
{
    m_serialPort = new QSerialPort(this);

    connect(m_serialPort, &QSerialPort::readyRead, this, &SerialPortManager::onReadyRead);
    connect(m_serialPort, &QSerialPort::errorOccurred, [this](QSerialPort::SerialPortError error) {
        QString status;
        switch (error) {
            case QSerialPort::NoError:
                status = "正常";
                break;
            case QSerialPort::DeviceNotFoundError:
                status = "未找到设备";
                break;
            case QSerialPort::PermissionError:
                status = "权限不足";
                break;
            case QSerialPort::OpenError:
                status = "已被占用";
                break;
            case QSerialPort::NotOpenError:
                status = "未打开";
                break;
            case QSerialPort::WriteError:
                status = "写入失败";
                break;
            case QSerialPort::ReadError:
                status = "读取失败";
                break;
            case QSerialPort::ResourceError:
                status = "设备已断开";
                break;
            default:
                status = QString("错误 (代码: %1)").arg(static_cast<int>(error));
        }
        emit portStatusChanged(m_portName, status, error == QSerialPort::NoError);
    });
}

SerialPortManager::~SerialPortManager()
{
    closeSerialPort();
}

bool SerialPortManager::initSerialPort(const QString &portName, qint32 baudRate,
                                      QSerialPort::DataBits dataBits,
                                      QSerialPort::Parity parity,
                                      QSerialPort::StopBits stopBits)
{
    qInfo() << "initSerialPort 串口号：" << portName << "波特率：" << baudRate << "数据位" << dataBits
                << "校验方式：" << parity << "停止位：" << stopBits << "是否模拟：" << m_isSimulate;

    if (m_isSimulate) {
        emit portStatusChanged(portName, "模拟串口已初始化", true);
        return true;
    }

    // 如果已打开则先关闭
    closeSerialPort();

    m_portName = portName;
    m_serialPort->setPortName(portName);
    m_serialPort->setBaudRate(baudRate);
    m_serialPort->setDataBits(dataBits);
    m_serialPort->setParity(parity);
    m_serialPort->setStopBits(stopBits);
    m_serialPort->setFlowControl(QSerialPort::NoFlowControl);

    bool success = m_serialPort->open(QIODevice::ReadWrite);
    if( !success ){
        qCritical() << "串口打开失败，错误码：" << m_serialPort->error()
                        << "错误描述：" << m_serialPort->errorString();
        emit portStatusChanged(portName, "串口打开失败：" + m_serialPort->errorString(), false);
    }
    else{
        emit portStatusChanged(portName, "串口成功打开", true);
    }
    return success;
}

bool SerialPortManager::sendData(const QByteArray &data)
{
    qInfo() << "sendData:" << data;
    if (m_isSimulate) {
        qDebug() << "模拟发送数据：" << data;
        //QByteArray replyData = "模拟接收：" + data;
        QByteArray replyData = ":" + data;
        emit dataReceived("RS485_2", replyData);
        return true;
    }

    if (!m_serialPort->isOpen() ) {
        emit portStatusChanged(m_portName, "串口未打开", false);
        return false;
    }
    qint64 bytesWritten = m_serialPort->write(data);
    bool success = (bytesWritten == data.size());
    if (!success) {
        emit portStatusChanged(m_portName, QString("只发送%1字节").arg(bytesWritten), false);
    }
    return success;
}

void SerialPortManager::closeSerialPort()
{
    if (m_serialPort->isOpen()) {
        m_serialPort->close();
        emit portStatusChanged(m_portName, "串口已关闭", true);
    }
}

bool SerialPortManager::isSerialPortOpen() const
{
    return m_serialPort->isOpen();
}

void SerialPortManager::onReadyRead()
{
//    if (m_serialPort->isOpen()) {
//        QByteArray data = m_serialPort->readAll();
//        m_dataBuffer.append(newData);
//        if (!data.isEmpty()) {
//            emit dataReceived(m_portName, data);
//            //emit dataReceived("MCU_232", data);
//        }
//    }

    if (!m_serialPort->isOpen())
        return;

    QByteArray newData = m_serialPort->readAll();
    m_dataBuffer.append(newData);

    int separatorIndex;
    while ((separatorIndex = m_dataBuffer.indexOf(m_frameSeparator)) != -1) {
        QByteArray completeFrame = m_dataBuffer.left(separatorIndex + m_frameSeparator.size());
        m_dataBuffer.remove(0, separatorIndex + m_frameSeparator.size());
        if (!completeFrame.isEmpty()) {
            emit dataReceived(m_portName, completeFrame);
        }
    }

    return;
}

QStringList SerialPortManager::scanAvailablePorts()
{
    QStringList portNames;

    // 1. 遍历所有可用串口，打印完整信息（包括路径、是否占用）
    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
        // 打印完整设备路径（关键：确认是否包含 /dev/pts/xx）
        qInfo() << "发现串口: " << info.portName()  // 这里会显示 /dev/pts/1 等路径
                << " 占用状态: " << (info.isBusy() ? "是" : "否")
                << " 制造商: " << info.manufacturer()
                << " 描述: " << info.description();

        // 仅添加未占用的串口（注意：socat 创建的虚拟串口默认未占用）
        if (!info.isBusy()) {
            portNames << info.portName();
        }
    }

    // 3. 打印最终扫描到的列表（确认是否包含 /dev/pts/xx）
//    qInfo() << "最终可用串口列表: " << portNames;

    emit availablePortsChanged(portNames);
    return portNames;
}


